Window 表示窗口,在某些特殊的时候,比如需要在桌面或者锁屏上显示一些类似悬浮窗的效果,就需要用到 Window。Android 中所有的视图都是通过 Window 来呈现的,不管是 Activity、Dialog 还是 Toast,它们的视图实际上都是附加在 Window 上的。而 WindowManager 则提供了对这些 Window 的统一管理功能。
13.2.1 Window 与 WindowManager 的联系
为了分析 Window 的工作机制,我们需要了解如何使用 WindowManager 来添加一个 Window。
上面的伪代码看起来非常简单,在构建 WindowManager.LayoutParams 时,其中的 type 和 flags 参数比较重要。
flags 参数有很多选项,用来控制 Window 的显示特性。我们来看几个常用的选项。
表示此 Window 不需要获取焦点,不接收各种输入时间,此标记会同时启用 FLAG_NOT_TOUCH_MODEL,最终事件会直接传递给下层具有焦点的 Window。
自己 Window 区域内的事件自己处理;自己 Window 区域外的事件传递给底层 Window 处理。一般这个选项会默认开启,否则其他 Window 无法接收事件。
可以让此 Window 显示在锁屏上。
type 参数是 int 类型的,表示 Window 的类型。Window 有三种类型:应用 Window、子 Window 和系统 Window。应用 Window 对应着一个 Activity。子 Window 不能独立存在,它需要附属在特定的父 Window 中,比如 Dialog 就是一个子 Window。系统 Window 是需要声明权限才能创建的,比如 Toast 和系统状态栏都是系统 Window。
Window 是分层的,层级大的 Window 会覆盖在层级小的 Window 上面。
- 应用 Window 的层级范围:1 ~ 99。
- 子 Window 的层级范围:1000 ~ 1999。
- 系统 Window 的层级范围:2000 ~ 2999。
type 参数就对应这些数字。如果想让 Window 置于顶层,则采用较大的层级即可;如果是系统类型的 Window,则需要在 AndroidMenifest.xml 中配置如下权限声明,否则会报权限不足的错误。
WindowManager 提供的功能很简单,常用的只有三个方法,即添加 View、更新 View 和删除 View。这三个方法定义在 ViewManager 中,而 WindowManager 继承自 ViewManager。
13.2.2 示例:悬浮窗
代码: